#include "uart.h"
#include <rtthread.h>
#define LPUART_RX_BUFFER_SIZE 64
uint8_t LPUART_RX_BUFFER[LPUART_RX_BUFFER_SIZE];
UART_HandleTypeDef UART2_Handle;
UART_HandleTypeDef UART3_Handle;
GPIO_InitTypeDef RS485_DIR;
#define rs48_port GPIOC
#define rs485_pin GPIO_PIN_12


LPUART_HandleTypeDef LPUART_handler;
extern DMA_HandleTypeDef DMA_CH1_Handle;
DMA_HandleTypeDef DMA_UART2_TX_Handle;
DMA_HandleTypeDef DMA_UART2_RX_Handle;
extern void UART2_RX_DMA_ITC_Callback(void);
void DMA_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&DMA_UART2_TX_Handle);
    HAL_DMA_IRQHandler(&DMA_CH1_Handle);
    HAL_DMA_IRQHandler(&DMA_UART2_RX_Handle);
}
void HAL_LPUART_MSPInit(LPUART_HandleTypeDef *hlpuart)
{
    GPIO_InitTypeDef gpio_init;

    System_Module_Reset(RST_LPUART);
    gpio_init.Pin = GPIO_PIN_1 | GPIO_PIN_0; // TX PC1 RX PC0
    gpio_init.Mode = GPIO_MODE_AF_PP;
    gpio_init.Pull = GPIO_PULLUP;
    gpio_init.Alternate = GPIO_FUNCTION_1;
    HAL_GPIO_Init(GPIOC, &gpio_init);
    System_Module_Enable(EN_LPUART);
}
void luart_init(uint32_t fu32_Baudrate)
{
    LPUART_handler.Instance = LPUART;
    LPUART_handler.ConfigParam.BaudRate = fu32_Baudrate;
    LPUART_handler.ConfigParam.ClockSrc = LPUART_CLOCK_SOURCE_PLL_DIV;
    LPUART_handler.ConfigParam.Parity = LPUART_PARITY_NONE;
    LPUART_handler.ConfigParam.StopBits = LPUART_STOPBITS_ONE;
    LPUART_handler.ConfigParam.WordLength = LPUART_DATABITS_8;
    LPUART_handler.rx_buffer_size = sizeof(LPUART_RX_BUFFER);
    LPUART_handler.rx_buffer = LPUART_RX_BUFFER;

    HAL_LPUART_Init(&LPUART_handler);
}

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDef    GPIO_InitStruct ={0};

    if (huart->Instance == UART1)
    {
        /* Enable Clock */
        System_Module_Enable(EN_UART1);

        /* Initialization GPIO */
        /* A9:Tx  A10:Rx */
        GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Alternate = GPIO_FUNCTION_2;

        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        if (huart->Init.HwFlowCtl & UART_HWCONTROL_CTS)
        {
            /* A11:CTS */
            GPIO_InitStruct.Pin = GPIO_PIN_11;

            HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        }

        if (huart->Init.HwFlowCtl & UART_HWCONTROL_RTS)
        {
            /* A12:RTS */
            GPIO_InitStruct.Pin = GPIO_PIN_12;

            HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        }

        /* NVIC Config */
        NVIC_ClearPendingIRQ(UART1_IRQn);
        NVIC_SetPriority(UART1_IRQn, (1 << __NVIC_PRIO_BITS) - 2);
        NVIC_EnableIRQ(UART1_IRQn);
    }
    else if (huart->Instance == UART2)
    {
        /* Enable Clock */
        System_Module_Enable(EN_UART2);
        System_Module_Enable(EN_GPIOCD);
        /* Initialization GPIO */
        GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Alternate = GPIO_FUNCTION_2;

        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

        NVIC_ClearPendingIRQ(UART2_IRQn);
        NVIC_SetPriority(UART2_IRQn, (1U << __NVIC_PRIO_BITS) - 2);
        NVIC_EnableIRQ(UART2_IRQn);
    }
    else if (huart->Instance == UART3)
    {
        /* Enable Clock */
        System_Module_Enable(EN_UART3);
        System_Module_Enable(EN_GPIOCD);
        /* Initialization GPIO */
        GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Alternate = GPIO_FUNCTION_4;

        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        NVIC_ClearPendingIRQ(UART3_IRQn);
        NVIC_SetPriority(UART3_IRQn, (1U << __NVIC_PRIO_BITS) - 2);
        NVIC_EnableIRQ(UART3_IRQn);
    }
}
void rs485_ready_rx(void)
{
    HAL_GPIO_WritePin(rs48_port, rs485_pin, GPIO_PIN_CLEAR);
}
void rs485_ready_send(void)
{
    HAL_GPIO_WritePin(rs48_port, rs485_pin, GPIO_PIN_SET);
}
void Uart_Init(uint32_t fu32_Baudrate)
{
    
    UART2_Handle.Instance = UART2;
    UART2_Handle.Init.BaudRate = fu32_Baudrate;
    UART2_Handle.Init.WordLength = UART_WORDLENGTH_8B;
    UART2_Handle.Init.StopBits = UART_STOPBITS_1;
    UART2_Handle.Init.Parity = UART_PARITY_NONE;
    UART2_Handle.Init.Mode = UART_MODE_TX_RX_DEBUG;
    UART2_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    HAL_UART_Init(&UART2_Handle);

    DMA_UART2_TX_Handle.Instance = DMA_Channel2;
    DMA_UART2_TX_Handle.Init.Mode = DMA_NORMAL;
    DMA_UART2_TX_Handle.Init.Data_Flow = DMA_DATA_FLOW_M2P;
    DMA_UART2_TX_Handle.Init.Request_ID = REQ7_UART2_SEND;
    DMA_UART2_TX_Handle.Init.Source_Inc = DMA_SOURCE_ADDR_INCREASE_ENABLE;
    DMA_UART2_TX_Handle.Init.Desination_Inc = DMA_DST_ADDR_INCREASE_DISABLE;
    DMA_UART2_TX_Handle.Init.Source_Width = DMA_SRC_WIDTH_BYTE;
    DMA_UART2_TX_Handle.Init.Desination_Width = DMA_DST_WIDTH_BYTE;
    DMA_UART2_TX_Handle.DMA_ITC_Callback = NULL;
    HAL_DMA_Init(&DMA_UART2_TX_Handle);
    __HAL_LINK_DMA(UART2_Handle, HDMA_Tx, DMA_UART2_TX_Handle);

    DMA_UART2_RX_Handle.Instance = DMA_Channel3;
    DMA_UART2_RX_Handle.Init.Mode = DMA_NORMAL;
    DMA_UART2_RX_Handle.Init.Data_Flow = DMA_DATA_FLOW_P2M;
    DMA_UART2_RX_Handle.Init.Request_ID = REQ8_UART2_RECV;
    DMA_UART2_RX_Handle.Init.Source_Inc = DMA_SOURCE_ADDR_INCREASE_DISABLE;
    DMA_UART2_RX_Handle.Init.Desination_Inc = DMA_DST_ADDR_INCREASE_ENABLE;
    DMA_UART2_RX_Handle.Init.Source_Width = DMA_SRC_WIDTH_BYTE;
    DMA_UART2_RX_Handle.Init.Desination_Width = DMA_DST_WIDTH_BYTE;
    DMA_UART2_RX_Handle.DMA_ITC_Callback = UART2_RX_DMA_ITC_Callback;
    HAL_DMA_Init(&DMA_UART2_RX_Handle);
    __HAL_LINK_DMA(UART2_Handle, HDMA_Rx, DMA_UART2_RX_Handle);

    UART3_Handle.Instance = UART3;
    UART3_Handle.Init.BaudRate = 9600;
    UART3_Handle.Init.WordLength = UART_WORDLENGTH_8B;
    UART3_Handle.Init.StopBits = UART_STOPBITS_1;
    UART3_Handle.Init.Parity = UART_PARITY_NONE;
    UART3_Handle.Init.Mode = UART_MODE_TX_RX;
    UART3_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;

    RS485_DIR.Pin = rs485_pin;
    RS485_DIR.Mode = GPIO_MODE_OUTPUT_PP;
    RS485_DIR.Pull = GPIO_PULLUP;
    RS485_DIR.Alternate = GPIO_FUNCTION_0;
    HAL_GPIO_Init(rs48_port, &RS485_DIR);

    HAL_UART_Init(&UART3_Handle);
    rs485_ready_rx();
}
void LPUART_IRQHandler(void)
{
    HAL_LPUART_IRQHander(&LPUART_handler);
    NVIC_ClearPendingIRQ(LPUART_IRQn);
}
